import bluetooth
from lib.ble import util, led
from lib.ble.services.index import SERVICES
from utils import device
import asyncio
from lib.config.index import ble_config


class BleServer:
    def __init__(self):
        self.__ble = bluetooth.BLE()
        self.__ble.active(True)
        self.__name = ble_config.get_prefix() + device.get_id()
        self.__text = "esp32 BLE"

        self.register_services()
        self.handle_event()
        self.advertise()
        self.run_loop()

    def register_services(self):
        self.__services = self.__ble.gatts_register_services(SERVICES)
        self.__characters = util.get_ble_character_handler(self.__services)

    def get_character(self, name):
        if name in self.__characters:
            return self.__characters[name]
        return None

    def run_loop(self):
        loop = asyncio.get_event_loop()
        loop.create_task(self.init_tasks())
        loop.run_forever()

    async def init_tasks(self):
        while True:
            await asyncio.sleep(ble_config.get_interval())
            await self.update_character()

    async def update_character(self):
        self.__ble.gatts_write(
            self.get_character("oled_text_char"), self.__text.encode("ascii")
        )
        alloc_m = device.get_gc_alloc_mem()
        free_m = device.get_gc_free_mem()
        if ble_config.is_debug():
            print(alloc_m, free_m)
        self.__ble.gatts_write(
            self.get_character("gc_alloc_char"), str(alloc_m).encode("ascii")
        )
        self.__ble.gatts_write(
            self.get_character("gc_free_char"), str(free_m).encode("ascii")
        )

    def advertise(self):
        adv_header = b"\x02\x01\x05"
        adv_name = util.create_adv_name_data(self.__name)
        adv_resp = b"\x06\xFF\x41\x42\x43\x44\x45"
        adv_data = adv_header + adv_name
        self.__ble.gap_advertise(500, adv_data, resp_data=adv_resp)

    def handle_event(self):
        self.__ble.irq(self.ble_irp)

    def ble_irp(self, event, data):
        if ble_config.is_debug():
            print(event, data)
        if event == 1:  # 蓝牙连接
            led.ble_led_connected()
        if event == 2:  # 蓝牙断开
            led.ble_led_disconnected()
            self.advertise()
        if event == 3:  # Write事件
            conn_handle, char_handle = data
            buffer = self.__ble.gatts_read(char_handle)
            print(conn_handle, buffer)

    def notify_gc(self):
        pass


if __name__ == "__main__":
    server = BleServer()
